package com.weilx959.spt.plugin.e2sp.utils.sql.parser;

import com.weilx959.spt.plugin.e2sp.constant.ExcelToSqlConstants;
import com.weilx959.spt.plugin.e2sp.exception.ExcelException;
import com.weilx959.spt.plugin.e2sp.model.statement.DeleteStatement;
import com.weilx959.spt.plugin.e2sp.model.statement.Statement;
import com.weilx959.spt.plugin.e2sp.utils.ResourceBundleUtil;
import com.weilx959.spt.plugin.e2sp.utils.sql.SqlUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
import net.sf.jsqlparser.util.deparser.SelectDeParser;
import net.sf.jsqlparser.util.deparser.StatementDeParser;

import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import java.util.Optional;
import java.util.ResourceBundle;

/**
 * DELETE SQL解析器
 *
 * @author weilx
 * @since 2024-05-02
 */
@Slf4j
public class DeleteSQLParser implements SQLParser {
    private static final ResourceBundle bundle = ResourceBundleUtil.get();

    @Override
    public String parse(Statement statement) {
        DeleteStatement deleteStatement = SqlUtil.cast(statement, DeleteStatement.class);
        // table
        Delete delete = new Delete();
        delete.setTable(new Table(deleteStatement.getSchema(), deleteStatement.getTableName()));

        // where
        deleteStatement.getKeyColumnMap().forEach((key, value) -> {
            Expression expression;
            Expression valueExpression = SqlUtil.getValueExpression(value);

            if (valueExpression instanceof NullValue) { // 为空
                IsNullExpression isNullExpression = new IsNullExpression();
                isNullExpression.setLeftExpression(new Column(key));
                expression = isNullExpression;
            } else {
                expression = new EqualsTo(new Column(key), valueExpression);
            }
            Expression where = delete.getWhere();

            if (Objects.isNull(where)) {
                delete.setWhere(expression);
            } else {
                delete.setWhere(new AndExpression(where, expression));
            }
        });
        deleteStatement.setDelete(delete);
        StringBuilder sb = new StringBuilder();

        try {
            ExpressionDeParser expressionDeParser = Optional.ofNullable(deleteStatement.getDialect())
                    .orElse(ExcelToSqlConstants.DEFAULT_DIALECT)
                    .getDeparserClass()
                    .getDeclaredConstructor()
                    .newInstance();
            delete.accept(new StatementDeParser(expressionDeParser, new SelectDeParser(), sb));
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new ExcelException(bundle.getString("e2s.de-parse.delete.error"), e);
        }
        sb.append(ExcelToSqlConstants.SEMICOLON);
        return sb.toString();
    }
}
